#pragma once 
#include<iostream>
#include<vector>
#include <semaphore.h>
#include<pthread.h>
const static int defaultcap = 5;
template<class T> 
class RingQueue
{


private:

//P V 操作
void P(sem_t & sem )
{
sem_wait(&sem) ;//等待信号量
}

void V(sem_t & sem)
{
    sem_post(&sem) ;//发布信号量
}

   //加锁和解锁
   void Lock(pthread_mutex_t &mutex)
   {
    pthread_mutex_lock(&mutex);
   }

   void UnLock(pthread_mutex_t &mutex)
   {
    pthread_mutex_unlock(&mutex);
   }


public:

RingQueue(int cap =defaultcap)
:ringqueue_(cap)
,cap_(cap)
,c_step_(0)
,p_step_(0)
{
 //初始化信号量

 sem_init(&cdata_sem_,0,0);
 sem_init(&pspace_sem_,0,cap);


//初始化互斥量
     pthread_mutex_init(&c_mutex_, nullptr);
        pthread_mutex_init(&p_mutex_, nullptr);
}





void Push(  const T & in ) //生产者生产
{
    //空间资源减少，数据资源增多

    


  P(pspace_sem_);
  Lock(p_mutex_) ;//申请信号量是原子的，不需要加锁，所以再申请信号量之后在加锁
    ringqueue_[p_step_] =in ;
   
    
    //维持环形队列的环形特点
    p_step_++;
    p_step_ %= cap_;

  UnLock(p_mutex_) ;
     V(cdata_sem_);
 

}
void   Pop( T * out ) //消费者消费
{
 //空间资源增多，数据资源减少
P(cdata_sem_);

Lock(c_mutex_) ;//申请信号量是原子的，不需要加锁，所以再申请信号量之后在加锁
    *out =ringqueue_[c_step_]; //????


 //维持环形队列的环形特点
    c_step_++;
    c_step_ %= cap_;
UnLock(c_mutex_) ;
    V(pspace_sem_);
}




~RingQueue () 
{
    sem_destroy(&cdata_sem_);
    sem_destroy(&pspace_sem_);
  pthread_mutex_destroy(&c_mutex_);
        pthread_mutex_destroy(&p_mutex_);
}
private:
std::vector<T> ringqueue_ ;
   int cap_;  //数组的容量

    int c_step_;       // 消费者下标
    int p_step_;       // 生产者下标


        //信号量来保证生产者和消费者之间的互斥和同步
    sem_t cdata_sem_;  // 消费者关注的数据资源
    sem_t pspace_sem_; // 生产者关注的空间资源

    pthread_mutex_t c_mutex_;  // 消费者的锁
    pthread_mutex_t p_mutex_;   //生产者的锁
};